/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.device.modular.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import vip.xiaonuo.common.enums.BizPermissionEnum;
import vip.xiaonuo.device.core.enums.Constants;
import vip.xiaonuo.device.modular.entity.*;
import vip.xiaonuo.device.modular.mapper.*;
import vip.xiaonuo.device.vo.Result;

import java.util.Date;

/**
 * 设备api日志Service接口实现类
 *
 * @author levin
 * @date 2022/11/30 13:27
 **/
@Service("devicePermSingleService")
public class DevicePermSingleServiceImpl extends DeviceBaseService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CabinetInfoMapper cabinetInfoMapper;
    @Autowired
    private CabinetDoorMapper cabinetDoorMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private RelationMapper relationMapper;

    @Override
    protected Integer getReqType() {
        return Constants.GETDOORAUTH;
    }

    @Override
    protected Result handle(JSONObject param) {
        String cardNum = param.getString("cardnum");
        String cabinetId = param.getString("cabinetcode");
        String doorId = param.getString("doorcode");

        /**
         * 返回message中code注意（默认500），请避开。涉及到事件的触发！！！如下
         * 1、7000~7002
         */
        if (StringUtils.isBlank(cardNum)) {
            return Result.fail(7000, "无法识别的卡号");
        }

        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserNo, cardNum));
        if (user == null) {
            return Result.fail(7001, String.format("卡号%s不存在", cardNum));
        }
        if (user.getUserStatus().equals("DISABLED")) {
            return Result.fail(7002, String.format("卡号%s已停用", cardNum));
        }

        BizCabinetInfo cabinetInfo = cabinetInfoMapper.selectOne(new LambdaQueryWrapper<BizCabinetInfo>()
                .eq(BizCabinetInfo::getCabinetCode, cabinetId).last("limit 1"));
        if (cabinetInfo == null) {
            return Result.fail(String.format("柜子%s不存在", cabinetId));
        }


        BizCabinetDoor cabinetDoor = cabinetDoorMapper.selectOne(new LambdaQueryWrapper<BizCabinetDoor>()
                .eq(BizCabinetDoor::getCabinetInfoId, cabinetInfo.getId())
                .eq(BizCabinetDoor::getCabinetDoorCode, doorId).last("limit 1"));
        if (cabinetDoor == null) {
            return Result.fail(String.format("柜门%s不存在", doorId));
        }

        String userId = user.getId();
        // 如果用户是组柜管理员/柜子管理员/柜门管理员，默认有所有权限
        LambdaQueryWrapper<BizRelation> condition = new LambdaQueryWrapper<BizRelation>()
                .or(q -> q.eq(BizRelation::getCategory, "BIZ_RELATION_CABINET_INFO_AND_ADMIN_USER")
                        .eq(BizRelation::getObjectId, cabinetInfo.getId())
                        .eq(BizRelation::getTargetId, userId))
                .or(q -> q.eq(BizRelation::getCategory, "BIZ_RELATION_CABINET_DOOR_AND_ADMIN_USER")
                        .eq(BizRelation::getObjectId, cabinetDoor.getId())
                        .eq(BizRelation::getTargetId, userId));
        if (StringUtils.isNotEmpty(cabinetInfo.getCabinetGroupId())) {
            condition.or(q -> q.eq(BizRelation::getCategory, "BIZ_RELATION_CABINET_GROUP_AND_ADMIN_USER")
                    .eq(BizRelation::getObjectId, cabinetInfo.getCabinetGroupId())
                    .eq(BizRelation::getTargetId, userId));
        }
        long adminPermCount = relationMapper.selectCount(condition);
        if (adminPermCount > 0) return Result.ok(getData(user, true, true));


        if (cabinetInfo.getState() != 1) {
//            return Result.fail(String.format("柜子%s被停用", cabinetId));
            return Result.ok(getData(user, false, false));
        }

        if (cabinetDoor.getState() != 1) {
//            return Result.fail(String.format("柜门%s被停用", cabinetId));
            return Result.ok(getData(user, false, false));
        }

        // 判断用户是否有柜门权限是否冻结
        long userPermCabinetDoorFrozenCount = permissionMapper.selectCount(getFrozenCondition(userId).eq(BizCabinetPermission::getCabinetDoorId, cabinetDoor.getId()));
        // 柜门权限被冻结，直接返回被冻结
        if (userPermCabinetDoorFrozenCount > 0) return Result.ok(getData(user, false, false));

        // 柜门权限被授予，直接返回被授权
        long userPermCabinetDoorAuthorizedCount = permissionMapper.selectCount(getAuthorizedCondition(userId).eq(BizCabinetPermission::getCabinetDoorId, cabinetDoor.getId()));
        // 如果有柜门权限，直接返回有权限
        if (userPermCabinetDoorAuthorizedCount > 0) return Result.ok(getData(user, false, true));

        // 如果柜门是独立权限，并且没有给用户授权，直接返回无权限
        if (cabinetDoor.getSeparatedPermission() && userPermCabinetDoorAuthorizedCount == 0)
            return Result.ok(getData(user, false, false));

        // 判断柜子是否被冻结
        long userPermCabinetInfoFrozenCount = permissionMapper.selectCount(getFrozenCondition(userId).eq(BizCabinetPermission::getCabinetInfoId, cabinetInfo.getId()));
        // 柜子被冻结，直接返回无权限
        if (userPermCabinetInfoFrozenCount > 0) return Result.ok(getData(user, false, false));

        // 判断用户是否有柜子权限
        long userPermCabinetInfoAuthorizedCount = permissionMapper.selectCount(getAuthorizedCondition(userId).eq(BizCabinetPermission::getCabinetInfoId, cabinetInfo.getId()));
        // 如果有柜子权限，直接返回有权限
        if (userPermCabinetInfoAuthorizedCount > 0) return Result.ok(getData(user, false, true));

        // 如果组柜不为空，判断组柜上是否有权限
        if (StringUtils.isNotEmpty(cabinetInfo.getCabinetGroupId())) {
            // 判断组柜是否被冻结
            long userPermCabinetGroupFrozenCount = permissionMapper.selectCount(getFrozenCondition(userId).eq(BizCabinetPermission::getCabinetGroupId, cabinetInfo.getCabinetGroupId()));
            // 组柜被冻结，直接返回无权限
            if (userPermCabinetGroupFrozenCount > 0) return Result.ok(getData(user, false, false));

            // 判断用户是否有组柜权限
            long userPermCabinetGroupAuthorizedCount = permissionMapper.selectCount(getAuthorizedCondition(userId).eq(BizCabinetPermission::getCabinetGroupId, cabinetInfo.getCabinetGroupId()));
            // 如果有组柜权限，直接返回有权限
            if (userPermCabinetGroupAuthorizedCount > 0) return Result.ok(getData(user, false, true));
        }
        return Result.ok(getData(user, false, false));
    }

    private JSONObject getData(SysUser user, boolean isManager, boolean canOpenDoor) {
        JSONObject result = new JSONObject();
        result.put("id", user.getId());
        result.put("name", user.getName());
        result.put("ismanager", isManager);
        result.put("canopendoor", canOpenDoor);
        result.put("canscrapitem", false);
        result.put("canadditem", false);
        return result;
    }

    @Override
    protected void handleLog(ApiLog log, JSONObject param) {
        String cabinetCode = param.getString("cabinetcode");
        String doorcode = param.getString("doorcode");
        log.setCabinetCode(cabinetCode);
        log.setCabinetDoorCode(doorcode);
        String cardNum = param.getString("cardnum");
        if (StringUtils.isNotBlank(cardNum)) {
            SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserNo, param.getString("cardnum")));
            if (user != null) {
                log.setUserId(user.getId());
                log.setUserNo(user.getUserNo());
            }
        }
    }

    private LambdaQueryWrapper<BizCabinetPermission> getFrozenCondition(String userId) {
        return new LambdaQueryWrapper<BizCabinetPermission>()
                .eq(BizCabinetPermission::getUserId, userId)
                .eq(BizCabinetPermission::getDeleteFlag, "NOT_DELETE")
                .eq(BizCabinetPermission::getPermState, BizPermissionEnum.FROZEN.name());
    }

    private LambdaQueryWrapper<BizCabinetPermission> getAuthorizedCondition(String userId) {
        return new LambdaQueryWrapper<BizCabinetPermission>()
                .eq(BizCabinetPermission::getUserId, userId)
                .eq(BizCabinetPermission::getDeleteFlag, "NOT_DELETE")
                .eq(BizCabinetPermission::getPermState, BizPermissionEnum.AUTHORIZED.name())
                .and(q -> q.le(BizCabinetPermission::getPermStartTime, new Date())
                        .ge(BizCabinetPermission::getPermEndTime, new Date()));
    }
}
